import * as Joi from 'joi';

// 零隐患MFIS规范 - Joi配置验证
// 解决隐患：#2 异常处理不当，#15 密钥管理问题

export const configurationSchema = Joi.object({
  // 应用配置
  NODE_ENV: Joi.string()
    .valid('development', 'production', 'test')
    .default('development')
    .description('应用运行环境'),

  PORT: Joi.number()
    .default(4000)
    .description('服务端口'),

  APP_NAME: Joi.string()
    .default('endo-sight-uc-nestjs')
    .description('应用名称'),

  // JWT配置 - 零容忍安全验证
  JWT_SECRET: Joi.string()
    .min(32)
    .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/)
    .required()
    .description('JWT密钥必须至少32字符，包含大小写字母、数字和特殊字符'),

  JWT_EXPIRES_IN: Joi.string()
    .default('2h')
    .description('JWT过期时间'),

  JWT_REFRESH_SECRET: Joi.string()
    .min(32)
    .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]/)
    .required()
    .description('JWT刷新密钥'),

  JWT_REFRESH_EXPIRES_IN: Joi.string()
    .default('7d')
    .description('JWT刷新过期时间'),

  // 数据库配置
  DATABASE_URL: Joi.string()
    .required()
    .description('数据库连接URL'),

  DB_HOST: Joi.string()
    .default('localhost')
    .description('数据库主机'),

  DB_PORT: Joi.number()
    .default(3306)
    .description('数据库端口'),

  DB_NAME: Joi.string()
    .required()
    .description('数据库名称'),

  DB_USER: Joi.string()
    .required()
    .description('数据库用户名'),

  DB_PASSWORD: Joi.string()
    .min(8)
    .required()
    .description('数据库密码'),

  DB_CONNECTION_LIMIT: Joi.number()
    .default(20)
    .min(1)
    .max(100)
    .description('数据库连接池大小'),

  DB_CONNECTION_TIMEOUT: Joi.number()
    .default(30000)
    .min(5000)
    .description('数据库连接超时(毫秒)'),

  // Redis配置
  REDIS_HOST: Joi.string()
    .default('localhost')
    .description('Redis主机'),

  REDIS_PORT: Joi.number()
    .default(6379)
    .description('Redis端口'),

  REDIS_PASSWORD: Joi.string()
    .optional()
    .description('Redis密码'),

  REDIS_DB: Joi.number()
    .default(0)
    .description('Redis数据库'),

  REDIS_MAX_RETRIES: Joi.number()
    .default(3)
    .min(1)
    .description('Redis最大重试次数'),

  // AI推理服务配置
  AI_INFERENCE_URL: Joi.string()
    .uri()
    .required()
    .description('AI推理服务URL'),

  AI_SERVICE_TIMEOUT: Joi.number()
    .default(10000)
    .min(1000)
    .max(60000)
    .description('AI服务超时时间(毫秒)'),

  AI_CIRCUIT_BREAKER_THRESHOLD: Joi.number()
    .default(50)
    .min(10)
    .max(90)
    .description('AI熔断器错误率阈值(百分比)'),

  AI_CIRCUIT_BREAKER_TIMEOUT: Joi.number()
    .default(30000)
    .min(5000)
    .description('AI熔断器超时时间(毫秒)'),

  // 文件上传配置
  UPLOAD_PATH: Joi.string()
    .default('./uploads/medical_images')
    .description('文件上传路径'),

  MAX_FILE_SIZE: Joi.number()
    .default(10 * 1024 * 1024) // 10MB
    .min(1024) // 1KB
    .max(50 * 1024 * 1024) // 50MB
    .description('最大文件大小(字节)'),

  ALLOWED_FILE_TYPES: Joi.string()
    .default('jpg,jpeg,png,tiff')
    .description('允许的文件类型'),

  // 安全配置
  ALLOWED_ORIGINS: Joi.string()
    .default('http://localhost:8101')
    .description('允许的CORS源'),

  BCRYPT_ROUNDS: Joi.number()
    .default(12)
    .min(10)
    .max(15)
    .description('bcrypt加密轮数'),

  ARGON2_MEMORY: Joi.number()
    .default(65536)
    .description('Argon2内存使用量'),

  ARGON2_PARALLELISM: Joi.number()
    .default(4)
    .description('Argon2并行度'),

  ARGON2_TIME: Joi.number()
    .default(3)
    .description('Argon2时间成本'),

  // 限流配置
  RATE_LIMIT_WINDOW: Joi.number()
    .default(60000)
    .min(1000)
    .description('限流时间窗口(毫秒)'),

  RATE_LIMIT_MAX: Joi.number()
    .default(10)
    .min(1)
    .max(100)
    .description('限流最大请求数'),

  // 队列配置
  QUEUE_REDIS_DB: Joi.number()
    .default(1)
    .description('队列Redis数据库'),

  QUEUE_MAX_CONCURRENT: Joi.number()
    .default(5)
    .min(1)
    .max(20)
    .description('队列最大并发数'),

  QUEUE_DEFAULT_ATTEMPTS: Joi.number()
    .default(3)
    .min(1)
    .max(10)
    .description('队列默认重试次数'),

  QUEUE_BACKOFF_DELAY: Joi.number()
    .default(2000)
    .min(100)
    .description('队列退避延迟(毫秒)'),

  // 缓存配置
  CACHE_REDIS_DB: Joi.number()
    .default(2)
    .description('缓存Redis数据库'),

  CACHE_TTL: Joi.number()
    .default(300)
    .min(60)
    .description('缓存TTL(秒)'),

  CACHE_MAX: Joi.number()
    .default(1000)
    .min(100)
    .description('最大缓存条目数'),

  // 日志配置
  LOG_LEVEL: Joi.string()
    .valid('error', 'warn', 'info', 'debug', 'verbose')
    .default('info')
    .description('日志级别'),

  LOG_FORMAT: Joi.string()
    .valid('json', 'simple')
    .default('json')
    .description('日志格式'),

  // 监控配置
  HEALTH_CHECK_INTERVAL: Joi.number()
    .default(30000)
    .min(5000)
    .description('健康检查间隔(毫秒)'),

  METRICS_ENABLED: Joi.boolean()
    .default(true)
    .description('是否启用指标收集'),

  PERFORMANCE_MONITORING: Joi.boolean()
    .default(true)
    .description('是否启用性能监控'),

  // 零容忍安全配置
  MIN_SECRET_LENGTH: Joi.number()
    .default(32)
    .min(16)
    .description('最小密钥长度'),

  REQUIRE_UPPERCASE: Joi.boolean()
    .default(true)
    .description('要求密钥包含大写字母'),

  REQUIRE_LOWERCASE: Joi.boolean()
    .default(true)
    .description('要求密钥包含小写字母'),

  REQUIRE_NUMBERS: Joi.boolean()
    .default(true)
    .description('要求密钥包含数字'),

  REQUIRE_SPECIAL_CHARS: Joi.boolean()
    .default(true)
    .description('要求密钥包含特殊字符'),
}).unknown(true); // 允许额外环境变量

// 零容忍配置验证函数
export function validateConfiguration(config: Record<string, any>): void {
  const { error, value } = configurationSchema.validate(config, {
    allowUnknown: true,
    stripUnknown: false,
    abortEarly: true, // 遇到第一个错误即停止
  });

  if (error) {
    console.error('🚨 CRITICAL: 配置验证失败');
    console.error('错误详情:', error.details[0].message);
    console.error('配置项:', error.details[0].path.join('.'));

    // 零容忍策略：配置验证失败立即终止进程
    process.exit(1);
  }

  // 运行时强度检查
  validateSecretStrength(value);
}

// 密钥强度验证
function validateSecretStrength(config: Record<string, any>): void {
  const criticalSecrets = ['JWT_SECRET', 'JWT_REFRESH_SECRET'];

  for (const secretKey of criticalSecrets) {
    const secret = config[secretKey];

    if (!secret) {
      console.error(`🚨 CRITICAL: ${secretKey} 未配置`);
      process.exit(1);
    }

    // 检查是否为默认值
    if (secret.includes('your-') || secret.includes('example')) {
      console.error(`🚨 CRITICAL: ${secretKey} 使用了默认值，请更改为安全的密钥`);
      process.exit(1);
    }

    // 额外的强度检查
    if (isWeakSecret(secret)) {
      console.error(`🚨 CRITICAL: ${secretKey} 强度不足，请使用更复杂的密钥`);
      process.exit(1);
    }
  }

  console.log('✅ 配置验证通过');
}

// 弱密钥检测
function isWeakSecret(secret: string): boolean {
  // 检查常见弱密钥模式
  const weakPatterns = [
    /^(.)\1+$/, // 重复字符
    /^(123|abc|qwe)/i, // 常见序列
    /^(password|admin|test)/i, // 常见词汇
    /^[a-z]+$/, // 只有小写字母
    /^[A-Z]+$/, // 只有大写字母
    /^\d+$/, // 只有数字
  ];

  return weakPatterns.some(pattern => pattern.test(secret));
}